home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / info-service / gopher / Unix / GopherTools / gopherclone < prev    next >
Encoding:
Text File  |  1992-08-25  |  6.1 KB  |  164 lines

  1. #!/usr/local/bin/perl
  2. # gopherclone - clone gophers
  3.  
  4. # usage:
  5. # gopherclone [www style gopher reference]
  6. # gopherclone gopher://gopher.msen.com:70/cicnet
  7.  
  8. # original NNTP client suggested by eci386!clewis
  9. # socket code mailed to me by cmf@obie.cis.pitt.edu (Carl M. Fongheiser)
  10. # adaptation for gopher by emv@msen.com (Edward Vielmetti)
  11. # modification to indexer by alberti@boombox.micro.umn.edu (Bob Alberti)
  12.  
  13. # Configuration information -- change to reflect your site.
  14.  
  15. $_ = $ARGV[0] ? $ARGV[0] : 'gopher://gopher.micro.umn.edu:70/';
  16.  
  17. #If an argument exists, use it, otherwise use default
  18.  
  19. ($service, $host, $port, $path) = (/^(gopher:\/\/)([^:]+):(\d+)(.*)/); 
  20.  
  21. #If debug = 0, gopherclone runs silent.  =1 is a verbose run.  Commented
  22. #debug lines are annoyingly thorough
  23.  
  24. $DEBUG = 1;              #set this to 0 for silent operation
  25.  
  26. if ($host && $port && $path) {
  27.                          $DEBUG && print "host=$host; port=$port; path=$path\n";
  28.                          # Here's how to make your own socket.ph
  29.                          # cp /usr/include/sys/socket.h socket.h
  30.    require 'socket.ph';  # h2ph socket
  31.    chop($hostname = `hostname`);        # get host name in variable
  32.  
  33.    ($N) = &tcpconnect($host, $hostname);# open connection 
  34.    if ($path eq "/") {
  35.       $path = "";
  36.    }
  37.    &gopherlevel($host, $hostname, $path, N); # clone the gopher
  38.  
  39.    close(N);                            # close the connection.  NOTHING TO IT!
  40. }
  41. else {
  42.    print "Command format:\n\n";
  43.    print "   gopherclone service://host.name:port/path/\n\n";
  44.    print "If a directory in the path includes multiple words separated by spaces,\n";
  45.    print "(i.e. /path name/), surround the parameter string with single quotes:\n\n";
  46.    print "   goppherclone 'service://host.name:port/path name/'\n\n";
  47.  
  48. }
  49.  
  50. sub gopherlevel {          # Build a level of gopher directory before recursion
  51.    local($host, $hostname, $path, $N) = @_;
  52.                            $DEBUG && print "sending path=$path\n";
  53.    send(N,"$path\r\n",0);
  54.                            $DEBUG && print STDERR "$path\r\n";
  55.    local($dirnum, $docnum, $i, @doc, @dir); #avoid scoping errors
  56.    @doc = 0;               #call me a fuddy-duddy but I like to Know
  57.    @dir = 0;
  58.  
  59.    while(<N>)  {                 #While receiving data
  60.       chop;chop;                 # trim data
  61.       next if /^[\. ]*$/;        # quit if a period
  62.       s/^(.)// && ( $type = $1); # otherwise Type is first character
  63.       @G= split(/\t/);           # and split other fields on tabs
  64.  
  65.                                  #$DEBUG &&  print "Type=$type\n";
  66.                                  #$DEBUG &&  print "Name=$G[0]\n";
  67.                                  #$DEBUG &&  print "Path=$G[1]\n";
  68.                                  #$DEBUG &&  print "Host=$G[2]\n";
  69.                                  #$DEBUG &&  print "Port=$G[3]\n";
  70.  
  71.       next if (($host ne $G[2]) || ($G[3] ne $port)); # if a link, skip
  72.  
  73.       if ($type == 1)  {         # Add directories to the list of directories
  74.          $dirnum += 1;
  75.          $dir[$dirnum] = $G[1];  # to be built after all information received
  76.                       $DEBUG && print "$dirnum: $dir[$dirnum]\n";   
  77.       }
  78.  
  79.       if ($type == 0) {          # Add documents to the list of items
  80.          $docnum += 1;           #$DEBUG && print "document\n";
  81.          $doc[$docnum] = $G[1];  # to be fetched after all information received
  82.                      # $DEBUG && print "$docnum: $doc[$docnum]\n";
  83.       }
  84.    }
  85.    close(N);
  86.  
  87.                                  #$DEBUG && print "\n";
  88.  
  89.    for ($i = 1; $i <= $docnum; $i++) {   #Documents first, they're easy
  90.       @path = split('/',$doc[$i]);       #split along slashes
  91.       $filename = $path[$#path];         #take last item as filename
  92.       $filename = $filename ? $filename : "/";
  93.       open(FILE, ">$filename") || die "Couldn't open new file $filename: $!\n";
  94.  
  95.       ($N) = &tcpconnect($host, $hostname);
  96.          
  97.       if ($N) {                    # If connection good
  98.          send(N,"$doc[$i]\r\n", 0) || die "Send $d to $host barfed with: $!\n";
  99.          $DEBUG && print "Receiving $filename\n";
  100.          while (<N>) {
  101.                                    #$DEBUG && print $_;
  102.             next if /^[\.]*$/;     #loop til lone period
  103.             print FILE $_;         # Put the text in the file
  104.          }
  105.          close(FILE);
  106.       }
  107.       else {
  108.          die "Couldn't open tcp connection $N: $!\n";
  109.       }
  110.       close(N);
  111.    }
  112.  
  113.    for ($i = 1; $i <= $dirnum; $i++) {     # Make directories
  114.       @path = split('/',$dir[$i]);         # split off leading entries in path;
  115.       $dirname = $path[$#path];            # take last item as name
  116.                               $DEBUG && print "dirname: $dirname\n";
  117.       $_ = $dirname;                       #Bah, this is ungraceful, but 
  118.       if (/^\S/) {                         #sometimes $dirname is blank.
  119.          mkdir ($dirname, 0xfff) || die print "Mkdir $dirname: $!\n";
  120.       }
  121.       else {
  122.            next;
  123.       }
  124.       chdir ($dirname)        || die print "Chdir $dirname: $!\n";
  125.  
  126.       ($N) = &tcpconnect($host, $hostname);
  127.     
  128.       if ($N) {
  129.          &gopherlevel($host, $hostname, $dir[$i], N);
  130.          sleep(2);     #arbitrary sleeps give sockets time to close
  131.          chdir("..")          || die print "chdir up: $!\n"; 
  132.       }
  133.       else {
  134.          die "Couldn't open tcp connection $N: $!\n"; 
  135.       }
  136.       close(N);
  137.    }  
  138. }
  139.  
  140.  
  141. sub tcpconnect {                    #Get TCP info in place
  142.    local($host, $hostname) = @_;
  143.    $sockaddr = 'S n a4 x8';
  144.  
  145.                             #$DEBUG && print "host: $host, me: $hostname\n";
  146.  
  147.    ($name,$aliases,$proto) = getprotobyname('tcp');
  148.    ($name,$aliases,$port) = getservbyname($port, 'tcp')
  149.         unless $port =~ /^\d+$/;
  150.    ($name,$aliases,$type,$len,$thisaddr) = gethostbyname($hostname);
  151.    ($name,$aliases,$type,$len,$thataddr) = gethostbyname($host);
  152.  
  153.    $this = pack($sockaddr, &AF_INET, 0, $thisaddr);
  154.    $that = pack($sockaddr, &AF_INET, $port, $thataddr);
  155.  
  156.    sleep(2);
  157.  
  158.    socket(N, &PF_INET, &SOCK_STREAM, $proto) || die "socket: $!";
  159.    bind(N, $this)                            || die "bind: $!";
  160.    connect(N, $that)                         || die "connect: $!";
  161.  
  162.    return(N);
  163. }
  164.